<?php

declare(strict_types=1);

namespace App\Service;

use App\Model\UserModel;
use Carbon\Carbon;
use App\Constants\ErrorCode;
use App\Constants\RedisKey;
use App\Job\PullCharacterJob;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use Hyperf\AsyncQueue\Driver\DriverInterface;
use Swoole\Coroutine\System;
use function L1n6yun\HyperfJwt\auth;

class UserService
{
    /**
     * 注入DriverInterface
     * @var DriverInterface
     */
    protected DriverInterface $driver;

    public function __construct(DriverFactory $driverFactory)
    {
        $this->driver = $driverFactory->get('default');
    }

    /**
     * 玩家设备登录接口
     * @param string $device_id
     * @return array
     */
    public function userLogin(string $device_id): array
    {
        // 生成token
        $userInfo = UserModel::query()
            ->where('device_id', $device_id)
            ->first();
        if(!$userInfo){
            abort(ErrorCode::USER_LOGIN_FALSE);
        }
        $userInfo->token = auth()->login($userInfo);
        return $userInfo->toArray();
    }

    /**
     * 玩家设备退出登录接口
     * @return bool
     */
    public function userLogout(): bool
    {
        auth()->logout();
        return true;
    }

    /**
     * 玩家游戏特征数据接口
     * @param string $data_version
     * @return array
     */
    public function userCharacter(string $data_version): array
    {
        $uid = (int)auth()->user()->getJwtIdentifier();
        $user_character_key = RedisKey::getKey(RedisKey::USER_GAME_CHARACTER, $data_version, $uid);
        if (redis()->exists($user_character_key)) {
            $data = json_decode(redis()->get($user_character_key), true);
        }
        return $data ?? [];
    }

    /**
     * 投递拉取用户特征数据的任务.
     * @param array $params 数据
     * @param int $delay 延时时间 单位秒
     * @return bool
     */
    public function push(array $params, int $delay = 0): bool
    {
        $job = new PullCharacterJob($params);
        if($this->driver->ttl($job) < 0) {
            return $this->driver->push($job, $delay);
        }
        return false;
    }
}